﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities.Dispatcher;
using Common.Utilities;

namespace Workflows.Components.TextMining.EnumerationObjects
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class TableDataExtractorInstruction:InstructionBase
    {
        #region props
        private int _RunID;
        /// <summary></summary>
        public int RunID
        {
            get
            {
                return _RunID;
            }
            set
            {
                _RunID = value;
            }
        }

        private string _FileListXmlFilePath;
        /// <summary></summary>
        public string FileListXmlFilePath
        {
            get
            {
                return this._FileListXmlFilePath;
            }
            set
            {
                this._FileListXmlFilePath = value;
            }
        }

        private string _TableLayoutXmlFilePath;
        /// <summary></summary>
        public string TableLayoutXmlFilePath
        {
            get
            {
                return this._TableLayoutXmlFilePath;
            }
            set
            {
                this._TableLayoutXmlFilePath = value;
            }
        }

        private string _TableScanXmlFilePath;
        /// <summary></summary>
        public string TableScanXmlFilePath
        {
            get
            {
                return _TableScanXmlFilePath;
            }
            set
            {
                _TableScanXmlFilePath = value;
            }
        }

        private string _TableExtractorOutputFolder;
        /// <summary></summary>
        public string TableExtractorOutputFolder
        {
            get
            {
                return this._TableExtractorOutputFolder;
            }
            set
            {
                this._TableExtractorOutputFolder = value;
            }
        }

        private string _LogFilePath;
        /// <summary></summary>
        public string LogFilePath
        {
            get
            {
                return this._LogFilePath;
            }
            set
            {
                this._LogFilePath = value;
            }
        }

        private string _ErrFilePath;
        /// <summary></summary>
        public string ErrFilePath
        {
            get
            {
                return this._ErrFilePath;
            }
            set
            {
                this._ErrFilePath = value;
            }
        }

        private int _ThreadPoolSize;
        /// <summary></summary>
        public int ThreadPoolSize
        {
            get
            {
                return this._ThreadPoolSize;
            }
            set
            {
                this._ThreadPoolSize = value;
            }
        }

        private string _ConnStr;
        /// <summary></summary>
        public string ConnStr
        {
            get
            {
                return this._ConnStr;
            }
            set
            {
                this._ConnStr = value;
            }
        }

        private string _DocStatusOutputTable;
        /// <summary></summary>
        public string DocStatusOutputTable
        {
            get
            {
                return this._DocStatusOutputTable;
            }
            set
            {
                this._DocStatusOutputTable = value;
            }
        }

        private string _DocRecordOutputTable;
        /// <summary></summary>
        public string DocRecordOutputTable
        {
            get
            {
                return this._DocRecordOutputTable;
            }
            set
            {
                this._DocRecordOutputTable = value;
            }
        }

        private string _DocIDField;
        /// <summary></summary>
        public string DocIDField
        {
            get
            {
                return this._DocIDField;
            }
            set
            {
                this._DocIDField = value;
            }
        }

        private string _RunIDField;
        /// <summary></summary>
        public string RunIDField
        {
            get
            {
                return this._RunIDField;
            }
            set
            {
                this._RunIDField = value;
            }
        }

        private string _IsElectronicField;
        /// <summary></summary>
        public string IsElectronicField
        {
            get
            {
                return this._IsElectronicField;
            }
            set
            {
                this._IsElectronicField = value;
            }
        }

        private string _IsScannedField;
        /// <summary></summary>
        public string IsScannedField
        {
            get
            {
                return this._IsScannedField;
            }
            set
            {
                this._IsScannedField = value;
            }
        }

        private string _PagesField;
        /// <summary></summary>
        public string PagesField
        {
            get
            {
                return this._PagesField;
            }
            set
            {
                this._PagesField = value;
            }
        }

        private string _RecordCountField;
        /// <summary></summary>
        public string RecordCountField
        {
            get
            {
                return this._RecordCountField;
            }
            set
            {
                this._RecordCountField = value;
            }
        }

        private string _DocFlagField;
        /// <summary></summary>
        public string DocFlagField
        {
            get
            {
                return this._DocFlagField;
            }
            set
            {
                this._DocFlagField = value;
            }
        }

        private string _CommentsField;
        /// <summary></summary>
        public string CommentsField
        {
            get
            {
                return this._CommentsField;
            }
            set
            {
                this._CommentsField = value;
            }
        }

        private Dictionary<string,string> _SrcTgtFieldMappings;
        /// <summary></summary>
        public Dictionary<string,string> SrcTgtFieldMappings
        {
            get
            {
                return this._SrcTgtFieldMappings;
            }
            set
            {
                this._SrcTgtFieldMappings = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public TableDataExtractorInstruction():base(Guid.Empty,Guid.Empty)
        {
            this._RunID = 1;
            this._FileListXmlFilePath = string.Empty;
            this._TableLayoutXmlFilePath = string.Empty;
            this._TableScanXmlFilePath = string.Empty;
            this._TableExtractorOutputFolder = string.Empty;
            this._LogFilePath = string.Empty;
            this._ErrFilePath = string.Empty;
            this._ThreadPoolSize = 10;

            this._ConnStr = string.Empty;
            this._DocStatusOutputTable = string.Empty;
            this._DocRecordOutputTable = string.Empty;
            this._DocIDField = string.Empty;
            this._RunIDField = string.Empty;
            this._IsElectronicField = string.Empty;
            this._IsScannedField = string.Empty;
            this._PagesField = string.Empty;
            this._RecordCountField = string.Empty;
            this._DocFlagField = string.Empty;
            this._CommentsField = string.Empty;
            this._SrcTgtFieldMappings = new Dictionary<string, string>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="runID"></param>
        /// <param name="componentID"></param>
        /// <param name="jobTicketID"></param>
        /// <param name="fileListFilePath"></param>
        /// <param name="tableScanOutputFilePath"></param>
        /// <param name="tableLayoutFilePath"></param>
        /// <param name="tableDataOutputFolderPath"></param>
        /// <param name="logFilePath"></param>
        /// <param name="errFilePath"></param>
        /// <param name="threadPoolSize"></param>
        /// <param name="connStr"></param>
        /// <param name="statusTable"></param>
        /// <param name="recordTable"></param>
        /// <param name="docIDField"></param>
        /// <param name="runIDField"></param>
        /// <param name="isElectronicField"></param>
        /// <param name="isScannedField"></param>
        /// <param name="pageField"></param>
        /// <param name="recCountField"></param>
        /// <param name="docFlagField"></param>
        /// <param name="commentField"></param>
        /// <param name="srcTgtFieldMappings"></param>
        public TableDataExtractorInstruction(Guid componentID, Guid jobTicketID,
            int runID,
            string fileListFilePath,
            string tableScanOutputFilePath,
            string tableLayoutFilePath,
            string tableDataOutputFolderPath,
            string logFilePath,
            string errFilePath,
            int threadPoolSize, 
            string connStr,
            string statusTable,
            string recordTable,
            string docIDField,
            string runIDField,
            string isElectronicField,
            string isScannedField,
            string pageField,
            string recCountField,
            string docFlagField,
            string commentField,
            Dictionary<string,string> srcTgtFieldMappings) 
            : base(componentID, jobTicketID)
        {
            this._RunID = runID;
            this._FileListXmlFilePath = fileListFilePath;
            this._TableScanXmlFilePath = tableScanOutputFilePath;
            this._TableLayoutXmlFilePath = tableLayoutFilePath;
            this._TableExtractorOutputFolder = tableDataOutputFolderPath;
            this._LogFilePath = logFilePath;
            this._ErrFilePath = errFilePath;
            this._ThreadPoolSize = threadPoolSize;

            this._ConnStr = connStr;
            this._DocStatusOutputTable = statusTable;
            this._DocRecordOutputTable = recordTable;
            this._DocIDField = docIDField;
            this._RunIDField = runIDField;
            this._IsElectronicField = isElectronicField;
            this._IsScannedField = isScannedField;
            this._PagesField = pageField;
            this._RecordCountField = recCountField;
            this._DocFlagField = docFlagField;
            this._CommentsField = commentField;
            this._SrcTgtFieldMappings = srcTgtFieldMappings;
        }
        #endregion 

        /// <summary>
        /// instantiated from xml
        /// "&lt;Instructions&gt;&lt;Instruction&gt;&lt;/Instruction&gt;&lt;/Instruction&gt;", must
        /// instantiate from first child of root node
        /// </summary>
        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                TableDataExtractorInstruction instruction = new TableDataExtractorInstruction();
                instruction.OwnerComponentID = new Guid(xNode.Attributes.GetNamedItem("ComponentID").Value);
                instruction.OwnerWorkerInstanceID = new Guid(xNode.Attributes.GetNamedItem("WorkerID").Value);
                instruction.SubmitTime = DateTime.Parse(xNode.Attributes.GetNamedItem("SubmitTime").Value);
                instruction.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("StartTime").Value);

                instruction.RunID = int.Parse(XmlDataUtil.GetAttributeValue(xNode, "RunID", "-1"));
                instruction.FileListXmlFilePath = XmlDataUtil.GetAttributeValue(xNode, "FileListXmlFilePath", "");
                instruction.TableScanXmlFilePath = XmlDataUtil.GetAttributeValue(xNode, "TableScanOutputXmlFilePath", "");
                instruction.TableLayoutXmlFilePath = XmlDataUtil.GetAttributeValue(xNode, "TableLayoutXmlFilePath", "");
                instruction.TableExtractorOutputFolder = XmlDataUtil.GetAttributeValue(xNode, "ResultFilePath", "");
                instruction.LogFilePath = XmlDataUtil.GetAttributeValue(xNode, "LogFilePath", "");
                instruction.ErrFilePath = XmlDataUtil.GetAttributeValue(xNode, "ErrFilePath", "");
                instruction.ThreadPoolSize = int.Parse(XmlDataUtil.GetAttributeValue(xNode, "ThreadPoolSize", "10"));

                instruction.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnectionString", "");
                instruction.DocStatusOutputTable = XmlDataUtil.GetAttributeValue(xNode, "StatusOutputTable", "");
                instruction.DocRecordOutputTable = XmlDataUtil.GetAttributeValue(xNode, "RecordOutputTable", "");
                instruction.DocIDField = XmlDataUtil.GetAttributeValue(xNode, "DocIDField", "");
                instruction.RunIDField = XmlDataUtil.GetAttributeValue(xNode, "RunIDField", "");
                instruction.IsElectronicField = XmlDataUtil.GetAttributeValue(xNode, "IsElectronicField", "");
                instruction.IsScannedField = XmlDataUtil.GetAttributeValue(xNode, "IsScannedField", "");
                instruction.PagesField = XmlDataUtil.GetAttributeValue(xNode, "PageField", "");
                instruction.RecordCountField = XmlDataUtil.GetAttributeValue(xNode, "RecordCountField", "");
                instruction.DocFlagField = XmlDataUtil.GetAttributeValue(xNode, "FlagField", "");
                instruction.CommentsField = XmlDataUtil.GetAttributeValue(xNode, "CommentField", "");

                XmlNodeList mappingNodes = xNode.SelectNodes("FieldMappings/FieldMapping");
                if (mappingNodes != null && mappingNodes.Count > 0)
                {
                    instruction.SrcTgtFieldMappings = new Dictionary<string, string>();
                    foreach (XmlNode mappingNode in mappingNodes)
                    {
                        string srcFieldName = XmlDataUtil.GetAttributeValue(mappingNode, "FieldNameInFile", "");
                        if (!instruction.SrcTgtFieldMappings.ContainsKey(srcFieldName))
                        {
                            string tgtFieldName = XmlDataUtil.GetAttributeValue(mappingNode, "FieldNameInTable", "");
                            instruction.SrcTgtFieldMappings.Add(srcFieldName, tgtFieldName);
                        }
                    }
                }

                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate instruction: invalid type specified in xml node");
            }
        }

        /// <summary>serialize settings to xml</summary>
        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "RunID", this.RunID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FileListXmlFilePath", this.FileListXmlFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableScanOutputXmlFilePath", this.TableScanXmlFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableLayoutXmlFilePath", this.TableLayoutXmlFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ResultFilePath", this.TableExtractorOutputFolder);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "LogFilePath", this.LogFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ErrFilePath", this.ErrFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ThreadPoolSize", this.ThreadPoolSize.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnectionString", this.ConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StatusOutputTable", this.DocStatusOutputTable);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "RecordOutputTable", this.DocRecordOutputTable);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "DocIDField", this.DocIDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "RunIDField", this.RunIDField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "IsElectronicField", this.IsElectronicField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "IsScannedField", this.IsScannedField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "PageField", this.PagesField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "RecordCountField", this.RecordCountField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FlagField", this.DocFlagField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "CommentField", this.CommentsField);

            if (this.SrcTgtFieldMappings != null && this.SrcTgtFieldMappings.Count > 0)
            {
                XmlNode mappingRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldMappings");
                foreach (string srcField in this.SrcTgtFieldMappings.Keys)
                {
                    string tgtFieldName = this.SrcTgtFieldMappings[srcField];
                    XmlNode mappingNode = XmlDataUtil.AddElement(ref xDoc, mappingRootNode, "FieldMapping");
                    XmlDataUtil.UpdateAttribute(ref xDoc, mappingNode, "FieldNameInFile", srcField);
                    XmlDataUtil.UpdateAttribute(ref xDoc, mappingNode, "FieldNameInTable", tgtFieldName);
                }
            }

            return xNode;
        }
    }
}
